home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 1.iso
/
toolbox
/
src
/
exampleCode
/
opengl
/
extensions
/
samples
/
lens.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-11-11
|
29KB
|
1,130 lines
/*
* Copyright (c) 1994 Silicon Graphics, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that (i) the above copyright notices and this permission
* notice appear in all copies of the software and related documentation,
* and (ii) the name of Silicon Graphics may not be used in any
* advertising or publicity relating to the software without the specific,
* prior written permission of Silicon Graphics.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL,
* INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
* DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
/*
* lens - Roam around a very large image using textures tiles.
*
* Demonstrates the use of subtexture and texture color table extensions.
*
* $Revision: 1.1 $
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <bstring.h>
#include <math.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <X11/keysym.h>
#include <gl/image.h>
#include "xwindow.h"
#include "util.h"
#if!defined(GL_EXT_subtexture) || !defined(GL_EXT_abgr)
BOTH EXT_subtexture and EXT_abgr must be defined
#else
/* set to 1 for debug.. slower, but includes error checking */
#define DEBUG 0
/* a word the size of 4 bytes (e.g. an RGBA pixel) */
typedef unsigned int u_int32;
typedef struct tileimg {
int xsize, ysize;
int xtiles, ytiles;
int tilexsize, tileysize;
u_int32 **tiles;
} tileimg;
tileimg *img = NULL;
#define GETTILE(IMG,TX,TY) ((IMG)->tiles[(TY)*(IMG)->xtiles+(TX)])
#define MAXWIDTH (4*4096)
/* size of the physical texture */
#define TEX_SIZE_S 1024
#define TEX_SIZE_T 1024
int Lminx = -TEX_SIZE_S;
int Lmaxx = -TEX_SIZE_S;
int Lminy = -TEX_SIZE_T;
int Lmaxy = -TEX_SIZE_T;
unsigned int tileXSize = 64;
unsigned int tileYSize = 64;
long winxsize, winysize;
int xorg, yorg;
float myangle = 0;
float zoom = 1;
GLboolean useTct;
u_int32 *bgdtile = NULL;
Display *dpy;
Window win;
tileimg *readTiles();
void changeTct(void);
void changeModel(void);
void rgbToPackedRgba(unsigned short *rbuf, unsigned short *gbuf,
unsigned short *bbuf, u_int32 *lbuf,int xsize);
void processEvents(void);
void makeMesh0(float x0, float x1, float y0, float y1,
float s0, float s1, float t0, float t1, float z, int nx,int ny);
void makeMesh1(float x0, float x1, float y0, float y1,
float s0, float s1, float t0, float t1, float z, int nx,int ny);
void makeMesh2(float x0, float x1, float y0, float y1,
float s0, float s1, float t0, float t1, float z, int nx,int ny);
void makeMesh3(float x0, float x1, float y0, float y1,
float s0, float s1, float t0, float t1, float z, int nx,int ny);
void makeTable1(void);
void makeTable2(void);
void makeTable3(void);
void makeTable4(void);
void drawTiles(tileimg *img, int xorg, int yorg, int winxsize, int winysize);
void makeRgbBgdTile(void);
void makeRgbaBgdTile(void);
void applyRgbaBgd(tileimg *img);
tileimg *readTiles(IMAGE *image, int tilexsize, int tileysize);
#if DEBUG
void chkError(char *msg);
#else
#define chkError
#endif
void usage(char *name, int exitStatus);
void
main(int argc, char **argv)
{
GLXContext ctx;
int visualAttr[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 1, None};
if (argc < 2)
usage(argv[0], EXIT_FAILURE);
if (argv[1][0] == '-' && argv[1][1] == 'h')
usage(argv[0], EXIT_SUCCESS);
winxsize = winysize = 768;
createWindowAndContext(&dpy, &win, &ctx, 0, 0, winxsize, winysize,
GL_TRUE, NULL, visualAttr, "lens");
/* Change the event mask to watch for motion and button release as well */
XSelectInput(dpy,win, ExposureMask | StructureNotifyMask | KeyPressMask |
ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
XFlush(dpy);
glClear(GL_COLOR_BUFFER_BIT);
glXSwapBuffers(dpy, win);
/*
* check for required extensions.
* we know an RE/REC/REV with "abgr" has limited "subtexture" support,
* but doesn't advertise it.
*/
if (!getExtension("GL_EXT_subtexture") &&
(strncmp("RE",glGetString(GL_RENDERER),2) ||
!getExtension("GL_EXT_abgr"))) {
fprintf(stderr,"Sorry, EXT_subtexture required.\n");
exit(EXIT_FAILURE);
}
#if defined(GL_SGI_texture_color_table)
if (!(useTct = getExtension("GL_SGI_texture_color_table"))) {
/*
* HACK - texture color table is not formally advertised.
* Try using it anyhow.
*/
glDisable(GL_TEXTURE_COLOR_TABLE_SGI);
if (glGetError() == GL_NO_ERROR) {
fprintf(stderr, "Assuming SGI_texture_color_table supported but not\
advertised\n");
useTct = GL_TRUE;
}
} else
useTct = GL_TRUE;
if (!useTct)
fprintf(stderr,
"SGI_texture_color_table is not supported by this renderer\n");
#else
useTct = GL_FALSE;
#endif
{
IMAGE *image = iopen(argv[1], "r");
int iclose(IMAGE *);
if (!image) {
fprintf(stderr,"%s: can't open input file %s\n",argv[0], argv[1]);
exit(EXIT_FAILURE);
}
if (argc > 2) {
tileXSize = atoi(argv[2]);
tileYSize = argc > 3 ? atoi(argv[3]) : tileXSize;
}
fprintf(stderr,"TILE{XSIZE, YSIZE} = %d,%d\n",tileXSize,tileYSize);
img = readTiles(image, tileXSize, tileYSize);
(void) iclose(image);
}
makeRgbaBgdTile();
applyRgbaBgd(img);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(0.5,0.5,0.0);
glScalef(.61,.61,1.);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.,1.,.1,10.);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.,0.,-1.5);
glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); /*default*/
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); /*default*/
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB5_EXT,TEX_SIZE_S,TEX_SIZE_T,0,
GL_RGBA,GL_UNSIGNED_BYTE,NULL);
#if DEBUG
chkError("after glTexImage2D");
#endif
xorg = -(img->xsize/2.0 - TEX_SIZE_S/2.0);
yorg = -(img->ysize/2.0 - TEX_SIZE_T/2.0);
makeMesh0(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
drawTiles(img,-xorg,-yorg,winxsize,winysize);
glXSwapBuffers(dpy, win);
chkError("before processEvents");
processEvents();
}
void
usage(char *name, int exitStatus)
{
fprintf(stderr,
"usage: %s [-h (for help)] inimage [[tileWidthAndHeight] or\
[tileWidth tileHeight]]\n", name);
fprintf(stderr,
"\tInteractively, `h/?' keys provide description of interface\n");
exit(exitStatus);
}
void
processEvents(void)
{
int lx, ly, mx, my;
float fx, fy;
int i;
int leftdown = 0;
while(1) {
int needredraw;
XEvent event;
XNextEvent(dpy, &event);
switch (event.type) {
case Expose: /* window needs to be redrawn */
{
/* skip all but last "Expose" event (X often sends 2 or 3) */
if (((XExposeEvent*) &event)->count == 0) {
drawTiles(img,-xorg,-yorg,winxsize,winysize);
glXSwapBuffers(dpy, win);
}
}
break;
case ConfigureNotify: /* window resize (or a move) occurred */
{
winxsize = ((XConfigureEvent*) &event)->width;
winysize = ((XConfigureEvent*)&event)->height;
glViewport(0, 0, winxsize, winysize);
drawTiles(img,-xorg,-yorg,winxsize,winysize);
glXSwapBuffers(dpy, win);
}
break;
case KeyPress:
{
KeySym keysym;
(void) XLookupString(&event.xkey, NULL, 0, &keysym, 0);
switch (keysym) {
case XK_Escape: /* ESC key */
exit(EXIT_SUCCESS);
break;
case XK_Up: /* up arrow */
zoom -= .02;
if (zoom < 0.02) zoom = 0.02;
drawTiles(img,-xorg,-yorg,winxsize,winysize);
glXSwapBuffers(dpy, win);
break;
case XK_Down: /* down arrow */
zoom += .02;
if (zoom > 1) zoom = 1;
drawTiles(img,-xorg,-yorg,winxsize,winysize);
glXSwapBuffers(dpy, win);
break;
case XK_w:
changeModel();
drawTiles(img,-xorg,-yorg,winxsize,winysize);
glXSwapBuffers(dpy, win);
break;
case XK_l: /* left arrow */
changeTct();
chkError("after changeTct");
drawTiles(img,-xorg,-yorg,winxsize,winysize);
glXSwapBuffers(dpy, win);
break;
case XK_h:
case XK_H:
case XK_question:
printf("\tUp/Down arrow - zoom in/out\n");
printf("\tRight arrow\n");
printf("\tl - cycle through texture lookup tables\n");
printf("\tw - cycle through warping effects\n");
printf("\tLeft mouse - drag image\n");
printf("\tMiddle/Right mouse - rotate image CCW/CW\n");
printf("\th/? - help\n");
printf("\tEsc - quit\n");
break;
}
}
break;
case ButtonPress:
{
switch (((XButtonEvent *)&event)->button) {
case 1:
leftdown = 1;
lx = ((XButtonEvent *)&event)->x;
ly = ((XButtonEvent *)&event)->y;
break;
case 2:
do {
myangle -= 1.0;
if (myangle < -360.0)
myangle += 360.0;
drawTiles(img, -xorg, -yorg, winxsize, winysize);
glXSwapBuffers(dpy, win);
} while(xGetButton(2, dpy, win));
break;
case 3:
do {
myangle += 1.0;
if (myangle > 360.0)
myangle -= 360.0;
drawTiles(img,-xorg,-yorg,winxsize,winysize);
glXSwapBuffers(dpy, win);
} while (xGetButton(3, dpy, win));
break;
}
}
break;
case MotionNotify: /* cursor moved (in window) */
/* absorb extra motion events... */
if (leftdown) {
XMotionEvent *ev = (XMotionEvent*)&event;
while (XEventsQueued(dpy, QueuedAfterReading)) {
XEvent tev;
XNextEvent(dpy, &tev);
if (tev.type == MotionNotify) {
ev = (XMotionEvent*)&tev;
} else {
XPutBackEvent(dpy, &tev);
break;
}
}
mx = ev->x;
my = ev->y;
if(mx != lx || my != ly) {
xorg += (mx - lx);
yorg += -(my - ly); /* in X, y is inverted (yuk) */
drawTiles(img, -xorg, -yorg, winxsize, winysize);
glXSwapBuffers(dpy, win);
lx = mx;
ly = my;
}
}
break;
case ButtonRelease:
if (((XButtonEvent *)&event)->button == 1)
leftdown = 0;
break;
}
#if DEBUG
chkError("processEvents");
#endif
}
}
void
changeModel(void)
{
static int model = 0;
model = (model + 1) % 4;
switch (model) {
case 0:
makeMesh0(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
break;
case 1:
makeMesh1(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
break;
case 2:
makeMesh3(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
break;
case 3:
makeMesh2(-1.5,1.5,-1.5,1.5,0.0,1.0,0.0,1.0,0.0,64,64);
break;
}
}
tileimg *
readTiles(IMAGE *image, int tilexsize, int tileysize)
{
int xsize, ysize, zsize;
int i, x, y, ntiles;
u_int32 *lptr;
u_int32 ***tiles;
tileimg *img;
unsigned short rbuf[MAXWIDTH];
unsigned short gbuf[MAXWIDTH];
unsigned short bbuf[MAXWIDTH];
u_int32 lbuf[MAXWIDTH];
xsize = image->xsize;
ysize = image->ysize;
zsize = image->zsize;
if (image->xsize > MAXWIDTH) {
printf("cannot handle image wider than %d pixels.\n", MAXWIDTH);
exit(EXIT_FAILURE);
}
img = (tileimg *) malloc(sizeof(tileimg));
img->xsize = xsize;
img->ysize = ysize;
img->xtiles = ((xsize-1)/tilexsize)+1;
img->ytiles = ((ysize-1)/tileysize)+1;
img->tilexsize = tilexsize;
img->tileysize = tileysize;
img->tiles =
(u_int32**) malloc(img->ytiles*img->xtiles * sizeof(u_int32*));
ntiles = img->xtiles*img->ytiles;
#if DEBUG
printf("begin malloc ntile %d size %d\n",ntiles,tilexsize*tileysize*4);
printf("\t\t tilexsize,tileysize: %d %d xsize,ysize %d %d xtiles\
ytiles:%d %d\n", tilexsize,tileysize,xsize,ysize,img->xtiles,img->ytiles);
#endif
for(i=0; i<ntiles; i++) {
img->tiles[i] =
(u_int32 *) malloc(tilexsize*tileysize*sizeof(u_int32));
}
#if DEBUG
printf("end malloc\n");
#endif
printf("Reading image..."); fflush(stdout);
for(y=0; y<ysize; y++) {
int getrow(IMAGE *image, unsigned short *buffer,
unsigned int y, unsigned int z);
if(zsize >= 3) {
getrow(image,rbuf,y,0);
getrow(image,gbuf,y,1);
getrow(image,bbuf,y,2);
rgbToPackedRgba(rbuf,gbuf,bbuf,lbuf,xsize);
} else {
getrow(image,rbuf,y,0);
rgbToPackedRgba(rbuf,rbuf,rbuf,lbuf,xsize);
}
for(x=0; x<img->xtiles; x++) {
lptr = GETTILE(img,x,y/tileysize) + (tilexsize*(y%tileysize));
bcopy(lbuf+x*tilexsize,lptr,tilexsize*sizeof(u_int32));
}
}
printf("Done\n"); fflush(stdout);
return img;
}
/*
* The following 4 procedures create meshes for the different kind of
* warping effects.
*/
#define MAXMESH 64
float Ml[4*2*(MAXMESH+1)*2 * (MAXMESH+1)];
void
makeMesh0(float x0, float x1, float y0, float y1,
float s0, float s1, float t0, float t1, float z, int nx,int ny)
{
float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
float v;
float *mp = Ml;
dx = (x1-x0)/nx;
dy = (y1-y0)/ny;
ds = (s1-s0)/nx;
dt = (t1-t0)/ny;
y = y0;
t = t0;
vb[2] = z;
while (y < y1) {
x = x0;
s = s0;
while(x <= x1) {
tb[0] = s; tb[1] = t;
vb[0] = x; vb[1] = y;
vb[2] = 0.0;
*mp++ = tb[0];
*mp++ = tb[1];
mp += 2;
*mp++ = vb[0];
*mp++ = vb[1];
*mp++ = vb[2];
mp++;
tb[1] = t+dt;
vb[1] = y+dy;
vb[2] = 0.0;
*mp++ = tb[0];
*mp++ = tb[1];
mp += 2;
*mp++ = vb[0];
*mp++ = vb[1];
*mp++ = vb[2];
mp++;
x += dx;
s += ds;
}
y += dy;
t += dt;
}
}
void
makeMesh1(float x0, float x1, float y0, float y1,
float s0, float s1, float t0, float t1, float z, int nx, int ny)
{
float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
float v;
float *mp = Ml;
float N = 2.0;
float B = -1.5;
dx = (x1-x0)/nx;
dy = (y1-y0)/ny;
ds = (s1-s0)/nx;
dt = (t1-t0)/ny;
y = y0;
t = t0;
vb[2] = z;
while (y < y1) {
x = x0;
s = s0;
while(x <= x1) {
tb[0] = s; tb[1] = t;
vb[0] = x; vb[1] = y;
v = N*N - x*x - y*y;
if (v < 0.0) v = 0.0;
vb[2] = sqrt(v) + B;
if (vb[2] < 0.) vb[2] = 0.0;
*mp++ = tb[0];
*mp++ = tb[1];
mp += 2;
*mp++ = vb[0];
*mp++ = vb[1];
*mp++ = vb[2];
mp++;
tb[1] = t+dt;
vb[1] = y+dy;
v = N*N - x*x - (y+dy)*(y+dy);
if (v < 0.0) v = 0.0;
vb[2] = sqrt(v) + B;
if (vb[2] < 0.) vb[2] = 0.0;
*mp++ = tb[0];
*mp++ = tb[1];
mp += 2;
*mp++ = vb[0];
*mp++ = vb[1];
*mp++ = vb[2];
mp++;
x += dx;
s += ds;
}
y += dy;
t += dt;
}
}
void
makeMesh2(float x0, float x1, float y0, float y1,
float s0, float s1, float t0, float t1, float z, int nx,int ny)
{
float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
float v;
float *mp = Ml;
float N2 = 4.0;
float B2 = -3.5;
dx = (x1-x0)/nx;
dy = (y1-y0)/ny;
ds = (s1-s0)/nx;
dt = (t1-t0)/ny;
y = y0;
t = t0;
vb[2] = z;
while (y < y1) {
x = x0;
s = s0;
while(x <= x1) {
tb[0] = s; tb[1] = t;
vb[0] = x; vb[1] = y;
v = N2*N2 - x*x - y*y;
if (v < 0.0) v = 0.0;
vb[2] = sqrt(v) + B2;
*mp++ = tb[0];
*mp++ = tb[1];
mp += 2;
*mp++ = vb[0];
*mp++ = vb[1];
*mp++ = vb[2];
mp++;
tb[1] = t+dt;
vb[1] = y+dy;
v = N2*N2 - x*x - (y+dy)*(y+dy);
if (v < 0.0) v = 0.0;
vb[2] = sqrt(v) + B2;
*mp++ = tb[0];
*mp++ = tb[1];
mp += 2;
*mp++ = vb[0];
*mp++ = vb[1];
*mp++ = vb[2];
mp++;
x += dx;
s += ds;
}
y += dy;
t += dt;
}
}
void
makeMesh3(float x0, float x1, float y0, float y1,
float s0, float s1, float t0, float t1, float z, int nx, int ny)
{
float y,x,s,t,dx,dy,ds,dt,vb[3],tb[2];
float v;
float *mp = Ml;
float N3 = 2.0;
float B3 = -1.0;
dx = (x1-x0)/nx;
dy = (y1-y0)/ny;
ds = (s1-s0)/nx;
dt = (t1-t0)/ny;
y = y0;
t = t0;
vb[2] = z;
while (y < y1) {
x = x0;
s = s0;
while(x <= x1) {
tb[0] = s; tb[1] = t;
vb[0] = x; vb[1] = y;
v = N3*N3 - x*x - y*y;
if (v < 0.0) v = 0.0;
vb[2] = sqrt(v) + B3;
if (vb[2] < 0.) vb[2] = 0.0;
vb[2] = -vb[2];
*mp++ = tb[0];
*mp++ = tb[1];
mp += 2;
*mp++ = vb[0];
*mp++ = vb[1];
*mp++ = vb[2];
mp++;
tb[1] = t+dt;
vb[1] = y+dy;
v = N3*N3 - x*x - (y+dy)*(y+dy);
if (v < 0.0) v = 0.0;
vb[2] = sqrt(v) + B3;
if (vb[2] < 0.) vb[2] = 0.0;
vb[2] = -vb[2];
*mp++ = tb[0];
*mp++ = tb[1];
mp += 2;
*mp++ = vb[0];
*mp++ = vb[1];
*mp++ = vb[2];
mp++;
x += dx;
s += ds;
}
y += dy;
t += dt;
}
}
void
drawMesh(int nx,int ny)
{
float *mp = Ml;
int i,j;
glColor4f(1,1,1,1);
for (i = ny+1; i; i--) {
glBegin(GL_TRIANGLE_STRIP);
for (j = nx+1; j; j--) {
glTexCoord2fv(mp); mp += 4;
glVertex3fv(mp); mp += 4;
glTexCoord2fv(mp); mp += 4;
glVertex3fv(mp); mp += 4;
}
glEnd();
}
}
void
loadtile(float s, float t, int x, int y, tileimg *img)
{
GLvoid *tile;
tile = (GLvoid *) (x < 0 || x >= img->xtiles || y < 0 || y >= img->ytiles ?
bgdtile : GETTILE(img,x,y));
glTexSubImage2DEXT(GL_TEXTURE_2D, 0, s*TEX_SIZE_S+.5, t*TEX_SIZE_T+.5,
tileXSize, tileYSize, GL_RGBA, GL_UNSIGNED_BYTE,
tile);
#if DEBUG
chkError("after glTexSubImage2D");
#endif
}
void
drawTiles(tileimg *img, int xorg, int yorg, int winxsize, int winysize)
{
int minx,maxx,miny,maxy;
float s0,t0;
int x, y, first,last;
glClear(GL_COLOR_BUFFER_BIT);
minx = xorg < 0 ? (xorg - img->tilexsize - 1)/img->tilexsize :
xorg/img->tilexsize;
maxx = (xorg + TEX_SIZE_S)/(float) img->tilexsize - 1;
miny = yorg < 0 ? (yorg-img->tileysize-1)/img->tileysize :
yorg/img->tileysize;
maxy = (yorg + TEX_SIZE_T)/(float) img->tileysize - 1;
/* Bring in any newly exposed tiles on the left */
if (minx < Lminx) {
for (x = minx; x < Lminx; x++) {
s0 = x * (tileXSize/(float) TEX_SIZE_S);
s0 -= (int) s0; /* get the fractional position */
if (s0 < 0.0)
s0 += 1.0;
for (y = miny; y <= maxy; y++) {
t0 = y * (tileYSize/(float) TEX_SIZE_T);
t0 -= (int) t0;
if (t0 < 0.0)
t0 += 1.0;
loadtile(s0, t0, x, y, img);
}
}
first = Lminx;
} else
first = minx;
/* Bring in newly exposed tiles on the right */
if (maxx > Lmaxx) {
x = Lmaxx > minx ? Lmaxx+1 : minx;
last = x - 1;
for (; x <= maxx; x++) {
s0 = x * (tileXSize/(float) TEX_SIZE_S);
s0 -= (int) s0; /* get the fractional position */
if (s0 < 0.0)
s0 += 1.0;
for (y = miny; y <= maxy; y++) {
t0 = y * (tileYSize/(float) TEX_SIZE_T);
t0 -= (int) t0;
if (t0 < 0.0)
t0 += 1.0;
loadtile(s0, t0, x, y, img);
}
}
} else
last = maxx;
/* Bring in newly exposed tiles on the bottom */
if (miny < Lminy) {
for (y = miny; y < Lminy; y++) {
t0 = y * (tileYSize/(float) TEX_SIZE_T);
t0 -= (int) t0; /* get the fractional position */
if (t0 < 0.0)
t0 += 1.0;
for (x = first; x <= last; x++) {
s0 = x * (tileXSize/(float) TEX_SIZE_S);
s0 -= (int) s0; /* get the fractional position */
if (s0 < 0.0)
s0 += 1.0;
loadtile(s0, t0, x, y, img);
}
}
}
/* Bring in newly exposed tiles on the top */
if (maxy > Lmaxy) {
for (y = Lmaxy+1 ; y <= maxy; y++) {
t0 = y * (tileYSize/(float) TEX_SIZE_T);
t0 -= (int) t0; /* get the fractional position */
if (t0 < 0.0)
t0 += 1.0;
for (x = first; x <= last; x++) {
s0 = x * (tileXSize/(float) TEX_SIZE_S);
s0 -= (int) s0; /* get the fractional position */
if (s0 < 0.0)
s0 += 1.0;
loadtile(s0, t0, x, y, img);
}
}
}
Lminx = minx;
Lmaxx = maxx;
Lminy = miny;
Lmaxy = maxy;
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(xorg/(float) TEX_SIZE_S+0.5,yorg/(float) TEX_SIZE_T+0.5,0.0);
glRotatef(myangle, 0, 0, 1); /* z rotate */
glScalef(.63*zoom,.63*zoom,1.);
glTranslatef(-.5,-.5,0.);
glMatrixMode(GL_MODELVIEW);
drawMesh(64,64);
}
void
changeTct(void)
{
#if defined(GL_SGI_texture_color_table)
static int lut = 0;
if (!useTct)
return;
lut = (lut + 1) % 5;
if (lut == 0) {
glDisable(GL_TEXTURE_COLOR_TABLE_SGI);
chkError("after disable TCT");
return;
}
glEnable(GL_TEXTURE_COLOR_TABLE_SGI);
chkError("after enable TCT");
switch (lut) {
case 1: makeTable1(); break;
case 2: makeTable2(); break;
case 3: makeTable3(); break;
case 4: makeTable4(); break;
}
#endif
}
void
makeTable1(void)
{
#if defined(GL_SGI_texture_color_table)
static unsigned long table[256];
static int done = 0;
int i;
float v;
int iv;
if (!done) {
for (i = 0; i < 256; i++){
v = i/255.0;
iv = powf(v,(float) 2.0) * 255;
table[i] = ((iv)<<24) | ((iv)<<16) | ((iv)<<8) | ((iv));
}
done = 1;
}
glColorTableSGI(GL_TEXTURE_COLOR_TABLE_SGI, GL_RGBA8_EXT, 256,
GL_RGBA, GL_UNSIGNED_BYTE, table);
#endif
}
void
makeTable2(void)
{
#if defined(GL_SGI_texture_color_table)
static unsigned long table[256];
static int done = 0;
int i;
float v;
int iv;
if (!done) {
for (i = 0; i < 256; i++) {
v = i/255.0;
iv = powf(v,(float) 1.0) * 255;
table[i] = ((iv)<<24) | ((iv)<<16) | ((iv)<<8) | ((iv));
}
done = 1;
}
glColorTableSGI(GL_TEXTURE_COLOR_TABLE_SGI, GL_RGBA8_EXT, 256,
GL_RGBA, GL_UNSIGNED_BYTE, table);
#endif
}
/*
* define DLIST first time, and call it every time.
*/
void
makeTable3(void)
{
#if defined(GL_SGI_texture_color_table)
static unsigned long table[256];
static GLuint list = 0;
int i;
float v;
int iv;
if (list == 0) {
for (i = 0; i < 256; i++){
v = i/255.0;
iv = powf(v,(float) 0.5) * 255;
table[i] = ((iv)<<24) | ((iv)<<16) | ((iv)<<8) | ((iv));
}
list = glGenLists(1);
glNewList(list, GL_COMPILE);
glColorTableSGI(GL_TEXTURE_COLOR_TABLE_SGI, GL_RGBA8_EXT, 256,
GL_RGBA, GL_UNSIGNED_BYTE, table);
glEndList();
}
glCallList(list);
#endif
}
/*
* Create an inverting color table ("negative" effect)
* use LUMINANCE table because R,G,B,A tables are the same.
*/
void
makeTable4(void)
{
#if defined(GL_SGI_texture_color_table)
static unsigned char table[256];
static int done = 0;
int i;
if (!done) {
for (i = 0; i < 256; i++) {
table[i] = 255-i;
}
done = 1;
}
glColorTableSGI(GL_TEXTURE_COLOR_TABLE_SGI, GL_RGBA8_EXT, 256,
GL_LUMINANCE, GL_UNSIGNED_BYTE, table);
#endif
}
void
rgbToPackedRgba(unsigned short *rbuf, unsigned short *gbuf,
unsigned short *bbuf, u_int32 *lbuf, int xsize)
{
char *cptr;
int i;
cptr = (char *) lbuf;
for (i = xsize; i; i--) {
*cptr++ = *rbuf++;
*cptr++ = *gbuf++;
*cptr++ = *bbuf++;
*cptr++ = 0x00;
}
}
/*
* "Draw" an rgb tile for the background.
*/
void
makeRgbBgdTile(void)
{
int i,j,grid;
char *ptr;
bgdtile = (u_int32 *) malloc(tileXSize*tileYSize*sizeof(u_int32)*3/4);
grid = 8;
ptr = (char *) bgdtile;
for (i=0; i<tileYSize; i++) {
for(j=0; j<tileXSize; j++) {
if(i%grid == 0 || j%grid == 0) {
*ptr++ = 0x0; *ptr++ = 0x0; *ptr++ = 0x40;
} else {
*ptr++ = 0x40; *ptr++ = 0x40; *ptr++ = 0x40;
}
}
}
}
/*
* "Draw" an rgba tile for the background.
*/
void
makeRgbaBgdTile(void)
{
int i,j,grid;
u_int32 *ptr;
bgdtile = (u_int32 *) malloc(tileXSize*tileYSize*sizeof(u_int32));
grid = 8;
ptr = (u_int32 *) bgdtile;
for (i=0; i<tileYSize; i++) {
for(j=0; j<tileXSize; j++) {
if(i%grid == 0 || j%grid == 0) {
*ptr++ = 0x40000000; /* red is the upper byte */
} else {
*ptr++ = 0x40404000;
}
}
}
}
void
applyBgd(tileimg *img)
{
int extras,y,x,i,j;
char *ptr,*bgd;
extras = img->xsize % img->tilexsize;
if (extras) {
for (y=0; y< img->ytiles; y++) {
ptr = (char *) GETTILE(img,img->xtiles-1,y);
bgd = (char *) bgdtile;
for (j = 0; j< img->tileysize; j++) {
ptr += 3*extras;
bgd += 3*extras;
for (i=extras; i< img->tilexsize; i++) {
*ptr++ = *bgd++;
*ptr++ = *bgd++;
*ptr++ = *bgd++;
}
}
}
}
extras = img->ysize % img->tileysize;
if (extras) {
for (x=0; x< img->xtiles; x++) {
ptr = (char *) GETTILE(img,x,img->ytiles-1);
bgd = (char *) bgdtile;
ptr += 3*extras* img->tilexsize;
bgd += 3*extras* img->tilexsize;
for (j = extras; j< img->tileysize; j++) {
for (i=0; i< img->tilexsize; i++) {
*ptr++ = *bgd++;
*ptr++ = *bgd++;
*ptr++ = *bgd++;
}
}
}
}
}
void
applyRgbaBgd(tileimg *img)
{
int extras,y,x,i,j;
char *ptr,*bgd;
extras = img->xsize % img->tilexsize;
if (extras) {
for (y=0; y< img->ytiles; y++) {
ptr = (char *) GETTILE(img,img->xtiles-1,y);
bgd = (char *) bgdtile;
for (j = 0; j< img->tileysize; j++) {
ptr += 4*extras;
bgd += 4*extras;
for (i=extras; i< img->tilexsize; i++) {
*ptr++ = *bgd++;
*ptr++ = *bgd++;
*ptr++ = *bgd++;
*ptr++ = *bgd++;
}
}
}
}
extras = img->ysize % img->tileysize;
if (extras) {
for (x=0; x< img->xtiles; x++) {
ptr = (char *) GETTILE(img,x,img->ytiles-1);
bgd = (char *) bgdtile;
ptr += 4*extras* img->tilexsize;
bgd += 4*extras* img->tilexsize;
for (j = extras; j< img->tileysize; j++) {
for (i=0; i< img->tilexsize; i++) {
*ptr++ = *bgd++;
*ptr++ = *bgd++;
*ptr++ = *bgd++;
*ptr++ = *bgd++;
}
}
}
}
}
#if DEBUG
void
chkError(char *msg)
{
GLenum err;
char *errstr;
while ((err = glGetError()) != GL_NO_ERROR) {
fprintf(stderr,
"ERROR: %s: glGetError returned %s (expected GL_NO_ERROR)\n",
msg, gluErrorString(err));
}
}
#endif
#endif /* defined on extensions (else part) */